package cn.js189.system.service.impl;

import cn.hutool.core.collection.CollStreamUtil;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.IdUtil;
import cn.js189.system.api.domain.SysInterCount;
import cn.js189.system.api.domain.SysInterCountDto;
import cn.js189.system.api.domain.SysLogPlus;
import cn.js189.system.mapper.SysLogPlusMapper;
import cn.js189.system.service.ISysLogPlusService;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Slf4j
@Service
public class SysLogPlusServiceImpl implements ISysLogPlusService {
	
	@Resource
	private SysLogPlusMapper sysLogPlusMapper;
	
	@Async
	@Override
	public void saveLog(SysLogPlus sysLogPlus) {
		sysLogPlusMapper.saveLog(sysLogPlus);
	}
	
	@Override
	public void saveOrEditData(SysInterCountDto sysInterCount) {
		log.info("保存接口调用统计开始......");
		List<SysInterCount> countList = sysInterCount.getSysInterCountList();
		Map<String, SysInterCount> batchAdd = new HashMap<>(1);
		Map<String, SysInterCount> batchEdit = new HashMap<>(1);
		Map<String, SysInterCount> countMap = new HashMap<>(1);
		if (countList != null && !countList.isEmpty()) {
			List<String> urlList = new ArrayList<>();
			countList.forEach(i->{
				urlList.add(i.getUrl());
				SysInterCount count = countMap.getOrDefault(i.getUrl(),new SysInterCount());
				long value = count.getInterCount() == null ? 0L : count.getInterCount();
				count.setUrl(i.getUrl());
				count.setInterCount(value + i.getInterCount());
				countMap.put(i.getUrl(),count);
			});
			List<SysInterCount> countByUrl = sysLogPlusMapper.getInterfaceCountByUrl(urlList);
			Map<String, SysInterCount> interMap = CollStreamUtil.toMap(countByUrl, SysInterCount::getUrl, i -> i);
			for (Map.Entry<String, SysInterCount> interCount : countMap.entrySet()) {
				SysInterCount value = interCount.getValue();
				SysInterCount count = interMap.get(value.getUrl());
				if (count == null || CharSequenceUtil.isBlank(count.getId())) {
					value.setId(IdUtil.fastSimpleUUID());
					batchAdd.put(value.getUrl(), value);
				} else {
					value.setId(count.getId());
					value.setInterCount(value.getInterCount() + count.getInterCount());
					batchEdit.put(value.getUrl(), value);
				}
			}
		}
		// 批量新增
		saveInterfaceCount(batchAdd);
		// 批量修改
		editInterfaceCount(batchEdit);
		log.info("保存接口调用统计结束......");
	}
	
	
	@Override
	public void saveInterfaceCount(Map<String, SysInterCount> batchMap) {
		List<SysInterCount> batchAddList = new ArrayList<>(1);
		// 批量新增
		batchMap.forEach((k, v) -> batchAddList.add(v));
		if (!batchAddList.isEmpty()) {
			log.info("batchAddList:{}", batchAddList);
			if (batchAddList.size() > 1000) {
				for (List<SysInterCount> interCountList : Lists.partition(batchAddList, 1000)) {
					sysLogPlusMapper.saveInterfaceCount(interCountList);
				}
			}else{
				sysLogPlusMapper.saveInterfaceCount(batchAddList);
			}
		}
	}
	
	@Override
	public void editInterfaceCount(Map<String, SysInterCount> batchMap) {
		List<SysInterCount> batchEditList = new ArrayList<>(1);
		batchMap.forEach((k, v) -> batchEditList.add(v));
		if (!batchEditList.isEmpty()) {
			// 数据超过1000条分批处理
			if (batchEditList.size() > 1000) {
				for (List<SysInterCount> interCountList : Lists.partition(batchEditList, 1000)) {
					sysLogPlusMapper.editInterfaceCount(interCountList);
				}
			}else{
				sysLogPlusMapper.editInterfaceCount(batchEditList);
			}
		}
	}
	
	/**
	 * 保存接口统计数据
	 *
	 * @param batchEdit  统计对象集合
	 * @param interCount 统计对象
	 * @return 结果
	 */
	private boolean putList(Map<String, SysInterCount> batchEdit, Map<String, SysInterCount> batchAdd, SysInterCount interCount) {
		SysInterCount addCount = batchAdd.get(interCount.getUrl());
		if (addCount != null) {
			addCount.setInterCount(addCount.getInterCount() + interCount.getInterCount());
			batchAdd.put(interCount.getUrl(), addCount);
			return true;
		}
		
		SysInterCount editCount = batchEdit.get(interCount.getUrl());
		if (editCount != null) {
			editCount.setInterCount(editCount.getInterCount() + interCount.getInterCount());
			batchEdit.put(interCount.getUrl(), editCount);
			return true;
		}
		
		return false;
	}
	
}
